#include "assert.h"
#include "fs/deffs.h"
#include "fs/inode.h"
#include "fs/vfs.h"

/**
 * @brief get the device object
 *
 * @param path
 * @param subpath
 * @param node_store
 * @return int
 */
static int
getDevice(char* path, char** subpath, inode_t** node_store) {
    int slash = -1, colon = -1;
    for (int i = 0; path[i] != '\0'; ++i) {
        if (path[i] == ':') {
            colon = i;
            break;
        }
        if (path[i] == '/') {
            slash = i;
            break;
        }
    }
    if (colon < 0 && slash != 0) {
        *subpath = path;
        return vfs_getCurrentDir(node_store);
    }
    if (colon > 0) {
        // device:path
        path[colon] = '\0';
        ++colon;
        // device:/path, skip '/'
        while (path[colon] == '/')
            ++colon;
        *subpath = path + colon;
        return vfs_getRoot(path, node_store);
    }

    // /path
    if (path[0] == '/') {
        int ret = vsf_getBootFS(node_store);
        if (ret != 0)
            return ret;
    } else {
        // :path
        assert(path[0] == ':');
        inode_t* node;
        int ret = vfs_getCurrentDir(&node);
        if (ret != 0)
            return ret;
    }
    // / /... or :/...
    ++path;
    while (*path == '/')
        ++path;
    *subpath = path;
    return 0;
}

/**
 * @brief get the inode according to the path filename
 *
 * @param path
 * @param node_store
 * @return int
 */
int
vfs_lookup(char* path, inode_t** node_store) {
    inode_t* node;
    int ret = getDevice(path, &path, &node);
    if (ret != 0)
        return ret;
    if (path[0] == '\0') {
        *node_store = node;
        return 0;
    }
    ret = vop_lookup(node, path, node_store);
    vop_refDec(node);  //?
    return ret;
}

/**
 * @brief translate name to vnode
 *
 * @param path
 * @param node_store
 * @param endp
 * @return int
 */
int  //? 与getDevice区别？
vfs_lookupParent(char* path, inode_t** node_store, char** endp) {
    inode_t* node;
    int ret = getDevice(path, &path, &node);
    if (ret != 0)
        return ret;
    *endp = path;
    *node_store = node;
    return 0;
}